package mirabilis.samples.cec2014;

import mirabilis.org.Evaluator;
import mirabilis.org.config.Configuration;
import mirabilis.org.individuals.Individual;
import mirabilis.org.individuals.real.DoubleChromosome;
import mirabilis.org.individuals.real.DoubleIndividual;
import mirabilis.org.termination.Termination;



public class Cec2014 extends Evaluator{
	
	//For each of the 30 functions
	public static double[] optima = new double[] 
	{	
		100,200,300,400,500,600,700,800,900,1000,
		1100,1200,1300,1400,1500,1600,1700,1800,1900,2000,
		2100,2200,2300,2400,2500,2600,2700,2800,2900,3000
	};
	
	public static long maxFEs = 10000*Configuration.chromosome_size;
	
	//0.01 x 10000D = 100D, 0.02 x ....
	public static double[] record14prints = new double[]{
		100*Configuration.chromosome_size, 200*Configuration.chromosome_size, 300*Configuration.chromosome_size, 500*Configuration.chromosome_size,
		1000*Configuration.chromosome_size, 2000*Configuration.chromosome_size, 3000*Configuration.chromosome_size, 4000*Configuration.chromosome_size, 
		5000*Configuration.chromosome_size, 6000*Configuration.chromosome_size, 7000*Configuration.chromosome_size, 8000*Configuration.chromosome_size,
		9000*Configuration.chromosome_size, 10000*Configuration.chromosome_size
	};
	
	public static int nextcec2014print = 0; //initialize the counter for records
	
	private testfunc tf;
	
	public Cec2014() {
		tf = new testfunc();
		Configuration.termination_max_evaluation = maxFEs; 
		/*
		// Copy/paste/alter the following code where necessary to keep record of the printing
			if(nextcec2014print < record14prints.length && record14prints[nextcec2014print] >= Termination.get_n_evaluation()){
				//Call command for printing
				nextcec2014print++;// increase the record count for the next printing call
			}
		*/
	}

	// The fitness is evaluated as the error
	public double evaluate(Individual ind){
		Termination.increment_evaluation();
		
		int func_num = Configuration.F;
		double[] x = ind.getChr().asdouble();
		double[] f = new double[1];
		try {
			tf.test_func(x,f,x.length,1,func_num);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		double error = f[0]-optima[func_num-1];
		ind.setFitness(error);
		return error;
	}

	
	public double hit_value() {//the problem is minimizing the error 
		return 0;
	}
	
	public Object clone() {
		Cec2014 pp = new Cec2014();
		return pp;
	}
	
	
	public static void main(String[] args) {
		Configuration.F=2;
		Configuration.chromosome_size=1;
		Configuration.range_max= 100;
		Configuration.range_min= -100;
		double step = (Configuration.range_max - Configuration.range_min) / 1000.0;
		
		Cec2014 bench = new Cec2014();
		
		for (double i=Configuration.range_min; i<=Configuration.range_max;i+=step){
			double[] genes = new double[Configuration.chromosome_size];
			for(int j=0;j<Configuration.chromosome_size;j++){
				genes[j] = i;
			}
			DoubleChromosome chromo = new DoubleChromosome(genes);
			Individual ind = new DoubleIndividual(chromo);
			
			
			
			bench.evaluate(ind);
			double[] d = ind.getChr().asdouble();
			for(int j=0;j<Configuration.chromosome_size;j++){
				System.out.print(d[j]+" ");
			}
			
			System.out.println(""+ind.getFitness());	
		}
		
	}
}
